/**
 * Copyright (c) 2015-2017, Henry Yang 杨勇 (gismail@foxmail.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lambkit.module.cms.rpc.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.lambkit.common.service.LambkitModelServiceImpl;
import com.lambkit.core.aop.AopKit;
import com.lambkit.db.sql.column.Example;
import com.lambkit.module.cms.Cms;
import com.lambkit.module.cms.core.layer.MenuTree;
import com.lambkit.module.cms.core.layer.SortKit;
import com.lambkit.module.cms.rpc.api.CmsCategoryService;
import com.lambkit.module.cms.rpc.model.CmsCategory;

/**
 * @author yangyong 
 * @website: www.lambkit.com
 * @email: gismail@foxmail.com
 * @date 2019-10-22
 * @version 1.0
 * @since 1.0
 */
public class CmsCategoryServiceImpl extends LambkitModelServiceImpl<CmsCategory> implements CmsCategoryService {
	
	private CmsCategory DAO = null;
	
	public CmsCategory dao() {
		if(DAO==null) {
			DAO = AopKit.singleton(CmsCategory.class);
		}
		return DAO;
	}

	@Override
	public List<CmsCategory> findListBySystemId(Long systemId, Long userId) {
		Example example = CmsCategory.sql().andSystemIdEqualTo(systemId).andUserIdEqualTo(userId).example();
		return find(example);
	}
	
	@Override
	public List<CmsCategory> treeBySystemId(Long systemId, Long userId) {
		// TODO Auto-generated method stub
		List<CmsCategory> categorys = findListBySystemId(systemId, userId);
		SortKit.toTree(categorys);
		return categorys;
	}
	
	@Override
	public List<MenuTree> menuTreeBySystemId(Long systemId, Long userId, int layer) {
		// TODO Auto-generated method stub
		Example example = CmsCategory.sql().andPidEqualTo(0L).andSystemIdEqualTo(systemId).andUserIdEqualTo(userId).example().setOrderBy("orders");
		List<CmsCategory> categorys = find(example);
		List<MenuTree> trees = new ArrayList<>();
		for (int i = 0; i < categorys.size(); i++) {
			trees.add(categorys.get(i).createMenuTree(layer));
		}
		return trees;
	}

	@Override
	public List<MenuTree> menuTreeByParentid(Long categoryId, Long userId, int layer) {
		// TODO Auto-generated method stub
		Example example = CmsCategory.sql().andPidEqualTo(categoryId).andUserIdEqualTo(userId).example().setOrderBy("orders");
		List<CmsCategory> categorys = find(example);
		List<MenuTree> trees = new ArrayList<>();
		for (int i = 0; i < categorys.size(); i++) {
			trees.add(categorys.get(i).createMenuTree(layer));
		}
		return trees;
	}

	@Override
	public List<CmsCategory> findCategoryListByArticleId(Long articleId) {
		SqlPara sqlPara = dao().getSqlPara("cms.findCategoryListByArticleId", articleId);
		return dao().find(sqlPara);
	}

	@Override
	public CmsCategory findFirstByFlag(String flag, Long userId) {
		Example example = CmsCategory.sql().andFlagEqualTo(flag).andUserIdEqualTo(userId).example();
		return findFirst(example);
	}

	@Override
	public List<CmsCategory> findAllChildById(Long categoryId, Long userId) {
		// TODO Auto-generated method stub
		return fillChild(categoryId, null, userId);
	}
	
	private List<CmsCategory> fillChild(Long categoryId, List<CmsCategory> plist, Long userId) {
		List<CmsCategory> clist = find(CmsCategory.sql().andPidEqualTo(categoryId).andUserIdEqualTo(userId).example());
		if(plist==null) {
			plist = clist;
		} else {
			plist.addAll(clist);
		}
		for (int i = 0; i < clist.size(); i++) {
			plist = fillChild(clist.get(i).getCategoryId(), plist, userId);
		}
		return plist;
	}

	@Override
	public List<CmsCategory> findByParenId(Long categoryId, Long userId) {
		// TODO Auto-generated method stub
		Example example = CmsCategory.sql().andPidEqualTo(categoryId).andUserIdEqualTo(userId).example();
		return find(example);
	}

	@Override
	public CmsCategory treeById(Long categoryId, Long userId) {
		// TODO Auto-generated method stub
		CmsCategory category = findById(categoryId);
		if(category.getUserId()!=userId) return null;
		category.setLayerNumber(0);
		addChild(category, userId);
		return category;
	}
	
	private void addChild(CmsCategory category, Long userId) {
		List<CmsCategory> list = findByParenId(category.getCategoryId(), userId);
		for (int i = 0; i < list.size(); i++) {
			CmsCategory m = list.get(i);
			m.setLayerNumber(category.getLayerNumber() + 1);
			category.addChild(m);
			addChild(m, userId);
		}
	}

	@Override
	public List<CmsCategory> treeByParenId(Long categoryId, Long userId) {
		// TODO Auto-generated method stub
		List<CmsCategory> list = findByParenId(categoryId, userId);
		for (int i = 0; i < list.size(); i++) {
			addChild(list.get(i), userId);
		}
		return list;
	}

	@Override
	public List<CmsCategory> linkParentById(Long categoryId) {
		// TODO Auto-generated method stub
		List<CmsCategory> cs = null;
		CmsCategory category = findById(categoryId);
		if(category!=null) {
			cs = new ArrayList<>();
			if(category.getPid()!=null || category.getPid()!=0) {
				cs = getParentCategory(cs, category.getPid());
			}
			cs.add(category);
		}
		return cs;
	}
	
	/**
	 * 遍历父类
	 * @param flds
	 * @param id
	 * @return
	 */
	private List<CmsCategory> getParentCategory(List<CmsCategory> flds, Long id) {
		CmsCategory catalog = findById(id);
		if(catalog!=null) {
			if(catalog.getPid()!=null || catalog.getPid()>0) {
				flds = getParentCategory(flds, catalog.getPid());
			}
			flds.add(catalog);
		}
		return flds;
	}
	
	@Override
	public List<Record> getAll(Long pid, Long userId, Long systemId) {
		StringBuilder sql = new StringBuilder();
		sql.append(" SELECT category_id as id,name as title,0 as filesize,alias as path,'' as suffix, 'folder' as t, description as brief, '' as tag, user_id as userId FROM cms_category WHERE pid=? ");
		if(systemId!=null) {
			sql.append(" and system_id=? ");
		}
		if(userId!=null) {
			sql.append(" and (user_id=? or user_id is null or user_id=1) ");
		}
		sql.append(" UNION ");
		sql.append(" SELECT f.file_id as id, f.file_name as title, f.file_size as filesize,f.file_uuid as path,f.file_ext as suffix,'file' as t, f.file_brief as brief, f.file_tag as tag, f.file_user_id as userId ");
		sql.append(" FROM cms_file f left join cms_file_category c on f.file_id = c.file_id where file_category_id=? or c.category_id=? ");
		
		sql.append(" UNION ");
		sql.append(" SELECT a.article_id as id, a.title, 0 as filesize,'' as path, '' as suffix, 'article' as t, a.description as brief, a.tag as tag, a.user_id as userId");
		sql.append(" FROM cms_article a left join cms_article_category c on a.article_id = c.article_id where c.category_id=? ");
		
		if(userId!=null) {
			if(systemId!=null) return Cms.db().find(sql.toString(), pid, systemId, userId, pid, pid, pid);
			else return Cms.db().find(sql.toString(), pid, userId, pid, pid, pid);
		} else {
			if(systemId!=null) return Cms.db().find(sql.toString(), pid, systemId, pid, pid, pid);
			else return Cms.db().find(sql.toString(), pid, pid, pid, pid);
		}
	}

	@Override
	public List<Record> getAllFile(Long pid, Long userId) {
		// TODO Auto-generated method stub
		if(userId!=null) {
			CmsCategory c = findById(pid);
			if(c!=null && c.getUserId()!=null && c.equals(1L) && c.getPublish()==0) {
				if(!c.getUserId().equals(userId)) {
					return null;
				}
			}
		}
		StringBuilder sql = new StringBuilder();
		sql.append(" SELECT f.file_id as id, f.file_name as title, f.file_size as filesize,f.file_uuid as path,f.file_ext as suffix,'file' as t, f.file_brief as brief, f.file_tag as tag, f.file_user_id as userId ");
		sql.append(" FROM cms_file f left join cms_file_category c on f.file_id = c.file_id where file_category_id=? or c.category_id=? ");
		sql.append(" UNION ");
		sql.append(" SELECT a.article_id as id, a.title, 0 as filesize,'' as path, '' as suffix, 'article' as t, a.description as brief, a.tag as tag, a.user_id as userId");
		sql.append(" FROM cms_article a left join cms_article_category c on a.article_id = c.article_id where c.category_id=? ");
		return Cms.db().find(sql.toString(), pid, pid, pid);
	}

	@Override
	public int remove(String ids, Long userId) {
		// TODO Auto-generated method stub
		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE ").append(getTableName()).append(" SET level=pid, pid=-1 ");
		sql.append(" WHERE category_id in (").append(ids).append(") and user_id=").append(userId);
		return Cms.db().update(sql.toString());
	}

	@Override
	public int move(Long pid, String ids, Long userId) {
		// TODO Auto-generated method stub
		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE ").append(getTableName()).append(" SET pid=").append(pid);
		sql.append(" WHERE category_id in (").append(ids).append(") and user_id=").append(userId);
		int n = Cms.db().update(sql.toString());
		return n;
	}

	@Override
	public Page<Record> getFileAndNote(int pageNumber, int pageSize, Long categoryId1, Long categoryId2, Long userId) {
		userId = userId == null ? 1L : userId;
		StringBuilder sql0 = new StringBuilder();
		sql0.append(" SELECT count(*) as cnt ");
		sql0.append(" FROM cms_file f left join cms_file_category c on f.file_id = c.file_id where (file_category_id=? or c.category_id=?) ");
		sql0.append(" and f.file_user_id=? ");
		sql0.append(" UNION ");
		sql0.append(" SELECT count(*) as cnt ");
		sql0.append(" FROM cms_article a left join cms_article_category c on a.article_id = c.article_id where c.category_id=? ");
		sql0.append(" and a.user_id=? ");
		List<Record> cnt = Cms.db().find(sql0.toString(), categoryId1, categoryId1, userId, categoryId2, userId);
		int totalRow = 0;
		for (Record record : cnt) {
			totalRow += record.getInt("cnt");
		}
		int offset = pageSize * (pageNumber - 1);
		StringBuilder sql = new StringBuilder();
		sql.append(" SELECT f.file_id as id, f.file_name as title, f.file_size as filesize,f.file_uuid as path,f.file_ext as suffix,'file' as t, f.file_brief as brief, f.file_tag as tag, f.file_create_time as ctime, f.file_user_id as userId ");
		sql.append(" FROM cms_file f left join cms_file_category c on f.file_id = c.file_id where (file_category_id=? or c.category_id=?) ");
		sql.append(" and f.file_user_id=? ");
		sql.append(" UNION ");
		sql.append(" SELECT a.article_id as id, a.title, 0 as filesize,'' as path, '' as suffix, 'article' as t, a.description as brief, a.tag as tag, a.ctime, a.user_id as userId ");
		sql.append(" FROM cms_article a left join cms_article_category c on a.article_id = c.article_id where c.category_id=? ");
		sql.append(" and a.user_id=? ORDER BY ctime desc LIMIT ?,?");
		SqlPara sqlPara = new SqlPara();
		sqlPara.setSql(sql.toString());
		sqlPara.addPara(categoryId1);
		sqlPara.addPara(categoryId1);
		sqlPara.addPara(userId);
		sqlPara.addPara(categoryId2);
		sqlPara.addPara(userId);
		List<Record> data = Cms.db().find(sql.toString(), categoryId1, categoryId1, userId, categoryId2, userId, offset, pageSize);
		Page<Record> page = new Page<>(data, pageNumber, pageSize, totalRow/pageSize, totalRow);
		return page;
	}

}
